﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;

namespace Reactor.Client.Controls
{
    public class SmallImageButton : ButtonBase
    {
        #region Fields

        private readonly Image _image;
        private Storyboard _mouseoverStoryboard;
        private Storyboard _mouseoutStoryboard;
        private DoubleAnimation _mouseoverWidthAnimation;
        private DoubleAnimation _mouseoverHeightAnimation;
        private DoubleAnimation _mouseoutWidthAnimation;
        private DoubleAnimation _mouseoutHeightAnimation;
        private readonly Duration _animationDuration = TimeSpan.FromMilliseconds(150);
        private double _scalePercentage = 10;

        #endregion

        public SmallImageButton()
        {
            ClickMode = ClickMode.Hover;

            var grid = new Grid();
            _image = new Image
            {
                Margin = new Thickness(2),
                MinHeight = 5,
                MinWidth = 5
            };
            grid.Children.Add(_image);

            Background = new SolidColorBrush(Colors.Transparent);
            BorderThickness = new Thickness(0);
            Height = double.IsNaN(Height) ? 20 : Height;
            Width = double.IsNaN(Width) ? 20 : Width;
            Content = grid;

            CreateStoryboards();

            MouseEnter += (s, e) => _mouseoverStoryboard.Begin();
            MouseLeave += (s, e) => _mouseoutStoryboard.Begin();
            
            MouseLeftButtonDown += (s, e) =>
                                        {
                                            _mouseoverStoryboard.Stop();
                                            _mouseoutStoryboard.Begin();
                                        };
            MouseLeftButtonUp += (s, e) =>
                                        {
                                            _mouseoutStoryboard.Stop();
                                            _mouseoverStoryboard.Begin();

                                            if(Command != null)
                                                Command.Execute(CommandParameter);
                                        };
        }

        private void CreateStoryboards()
        {
            _mouseoverStoryboard = new Storyboard();
            _mouseoverWidthAnimation = new DoubleAnimation();
            Storyboard.SetTarget(_mouseoverWidthAnimation, this);
            Storyboard.SetTargetProperty(_mouseoverWidthAnimation, new PropertyPath(WidthProperty));
            _mouseoverWidthAnimation.Duration = _animationDuration;
            _mouseoverStoryboard.Children.Add(_mouseoverWidthAnimation);

            _mouseoverHeightAnimation = new DoubleAnimation();
            Storyboard.SetTarget(_mouseoverHeightAnimation, this);
            Storyboard.SetTargetProperty(_mouseoverHeightAnimation, new PropertyPath(HeightProperty));
            _mouseoverHeightAnimation.Duration = _animationDuration;
            _mouseoverStoryboard.Children.Add(_mouseoverHeightAnimation);

            _mouseoutStoryboard = new Storyboard();
            _mouseoutWidthAnimation = new DoubleAnimation();
            Storyboard.SetTarget(_mouseoutWidthAnimation, this);
            Storyboard.SetTargetProperty(_mouseoutWidthAnimation, new PropertyPath(WidthProperty));
            _mouseoutWidthAnimation.Duration = _animationDuration;
            _mouseoutStoryboard.Children.Add(_mouseoutWidthAnimation);

            _mouseoutHeightAnimation = new DoubleAnimation();
            Storyboard.SetTarget(_mouseoutHeightAnimation, this);
            Storyboard.SetTargetProperty(_mouseoutHeightAnimation, new PropertyPath(HeightProperty));
            _mouseoutHeightAnimation.Duration = _animationDuration;
            _mouseoutStoryboard.Children.Add(_mouseoutHeightAnimation);

            UpdateAnimationScale();
        }

        public double ImageWidth
        {
            get { return _image.Width; }
            set { _image.Width = value; }
        }

        public double ImageHeight
        {
            get { return _image.Height; }
            set { _image.Height = value; }
        }

        public double OutterHeight
        {
            get { return Height; }
            set
            {
                Height = value;
                UpdateAnimationScale();
            }
        }

        public double OutterWidth
        {
            get { return Width; }
            set
            {
                Width = value;
                UpdateAnimationScale();
            }
        }

        private double GetScaleAmount(double baseAmount)
        {
            return baseAmount/_scalePercentage;
        }

        private void UpdateAnimationScale()
        {
            var widthScale = Width + GetScaleAmount(Width);
            var heightScale = Height + GetScaleAmount(Height);

            _mouseoverWidthAnimation.From = Width;
            _mouseoverWidthAnimation.To = widthScale;

            _mouseoverHeightAnimation.From = Height;
            _mouseoverHeightAnimation.To = heightScale;

            _mouseoutWidthAnimation.From = widthScale;
            _mouseoutWidthAnimation.To = Width;

            _mouseoutHeightAnimation.From = heightScale;
            _mouseoutHeightAnimation.To = Height;
        }

        #region ImageSource Dependency Property

        private static readonly PropertyMetadata PropMetadata = new PropertyMetadata((s, e) =>
        {
            var ctrl = s as SmallImageButton;
            if (ctrl == null) throw new InvalidOperationException("Control must be of type LargeBorderedImageButton.");

            if (e.NewValue is string)
                ctrl._image.Source = new BitmapImage(new Uri(Application.Current.Host.Source, e.NewValue.ToString()));
        });

        /// <summary>
        /// Identifies the ImageSource dependency property.
        /// </summary>
        public static DependencyProperty ImageSourceProperty =
            DependencyProperty.Register("ImageSource", typeof(string), typeof(SmallImageButton), PropMetadata);

        /// <summary>
        /// Image source for the image used as the template for this button.
        /// </summary>
        public string ImageSource
        {
            get { return (string)GetValue(ImageSourceProperty); }
            set { SetValue(ImageSourceProperty, value); }
        }

        #endregion

        #region Command Dependency Property

        public static new DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(SmallImageButton), null);

        public new ICommand Command
        {
            get { return (ICommand) GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value);}
        }

        #endregion
    }
}
